Site icon Rubilnik блог

Бот для записи на фитнес через GAS

В этой записи я поверхностно разберу возможность применения Google Apps Script для записи на занятия в фитнес в расписании на платформе mobifitness.ru.

Для начала нам надо убедиться, что расписание занятий вашего зала выполнено на этой платформе. Обычно упоминание можно увидеть в подвале расписания, а сам виджет вставлен в качестве iframe.

Далее нам понадобится взять заголовок авторизации, можно почитать заголовки через Postman или в консоли разработчика, нужен заголовок такого вида:

Authorization:  Bearer 0de079a2b23190df8026f********

Остальные заголовки неважны. Пользуюсь своим заголовком авторизации к каждому запросу уже на протяжении довольно долгого времени и пока проблем не было. Без авторизации данные отправить не удается.

Если перехватить запрос на запись, то выходит, что он обращается к https://mobifitness.ru/api/v6/account/reserve.json и передает clubId, fio, phone (неизменяемые) и scheduleId (который формируется нехитрым способом — сначала неизменяемая часть, затем дата занятия в формате ддммгггг). В вашем случае могут быть другие параметры. ClubID и ScheduleID можно взять в исходном коде страницы или запросе.

Кстати, для удобства записи вручную можно использовать следующий УРЛ адрес: https://mobifitness.ru/widget/792082?colored=1&lines=1&clubs=1337&trainer=19991&activity=757575

где clubs — айди клуба, trainer — айди конкретного тренера и activity — айди вашего типа занятия. Все это также можно взять из исходного кода страницы:

<div style="background-color: rgb(125, 205, 227);" data-color="#7dcde3" data-group="2666" data-real-id="*****22032024" data-activity="757575" data-room="4368" data-trainer="19991" data-sch-key="46" class="fitness-widget-cell">

Далее имея все эти данные создаем стандартно Apps Script через Google Sheets. Код с комментариями у меня получился такой:

// Telegram bot token from \@BotFather.
const botToken = "***:***";
// link to Google WebApp for working with doGet(e) responses.
const webAppUrl = "https://script.google.com/macros/s/****/exec";
// print the URL and OPTIONS of the request when executed, false by default.
const logRequest = "Optional[<logRequest>]";
// PropertiesService.getScriptProperties();
const service = "Optional[<service>]";
// set the parse mode, default "HTML".
const parseMode = "Optional[<parseMode>]";
const Bot = TGbot.bot({ botToken, webAppUrl }); // botToken, webAppUrl, logRequest, service, parseMode
// Bot.setParseMode("MarkdownV2"); // set the parse mode, default "HTML"
// Bot.setLogRequest(); // if you don't pass logRequest as an argument
// Bot.info(); // information about the bot and available methods


function sendMessage(text) {
const chat_id = "*******" // recipient's chat_id

// send message
const response = Bot.sendMessage({ chat_id: chat_id, text: text });

console.log(JSON.stringify(response, null, 7));
}

function logAction(action) {
  var timestamp = new Date();
  var sheet = SpreadsheetApp.openById('******').getSheetByName('Log');
  sheet.appendRow([timestamp, action]);
}

function registration () {
  let payload = {
  'clubId': '****',
  'fio': '****', 
  'phone': '****', 
  'scheduleId': generateScheduleId() 
  }
  let data = {
    "method": "post",
    "muteHttpExceptions": true,
    "headers": {'Authorization': 'Bearer 0de079a2b23******'},
    "payload": payload
  }

  let attempts = 0;
  let responseCode = null;
  let responseText = null;
  
  while (attempts < 5 && responseCode !== 200) {
    var response = UrlFetchApp.fetch('https://mobifitness.ru/api/v6/account/reserve.json', data);
    responseCode = response.getResponseCode();
    Logger.log("Код ответа: " + responseCode);
    responseText = JSON.parse(response.getContentText("UTF-8"));
    Logger.log(responseText);
    console.log(response);
    sendMessage("Код ответа: " + responseCode + "\n" + JSON.stringify(responseText));
    
    if (responseCode !== 200) {
      Utilities.sleep(5000); // Пауза в 5 секунд (5000 миллисекунд)
      attempts++;
    }
  }
  
  if (attempts >= 5 && responseCode !== 200) {
    sendMessage("Количество попыток исчерпано.");
  }
}

function generateScheduleId() {
  let nextFriday = getNextFriday();
  let year = nextFriday.getFullYear().toString().substring(2);
  let month = (nextFriday.getMonth() + 1).toString().padStart(2, '0'); // Месяцы в JS начинаются с 0
  let day = nextFriday.getDate().toString().padStart(2, '0');
  
  // Складываем все вместе
  let scheduleId = '1709606' + day + month + year;
  console.log("scheduleId: "+scheduleId);
  return scheduleId;
}

function getNextFriday() {
  let today = new Date();
  let daysUntilFriday = (5 - today.getDay() + 7) % 7; // Определяем количество дней до следующей пятницы
  let nextFriday = new Date(today.getTime() + daysUntilFriday * 24 * 60 * 60 * 1000); // Получаем дату следующей пятницы
  
  console.log("nextFriday: "+nextFriday);
  return nextFriday;
}

Обратите внимание что в моем примере используется библиотека TGbot. Её настройка это отдельная статья. Сделано это чтобы получать уведомления в телеграм такого вида:

Код ответа: 400
{"result":"error","errors":["Запись на занятие недоступна. Текущий интервал времени не попадает в разрешенный интервал записи."],"code":4020}
или
Код ответа: 200
{"result":"success"}

Все значения под звездочками *** необходимо заменить на свои. Основная функция это registration () — на неё и будем ставить триггер для автоматизации.

Переходим в раздел триггеров:

И добавляем новый триггер с параметрами как на скриншоте, главное укажите вашу дату начала регистрации на занятие:

На этом пока все…

Exit mobile version